let isDone: Boolean = false // Boolean
let isNumber: Number = 0 // number
let isString: String = '' // string
// let sym = Symbol() // symbol
// const obj = {
//   [sym]: 'semlinker'
// }
// 数组 两种方式，一种直接语法，一种泛型语法
let arr1: number[] = [1, 2, 3, 4, 5]
let arr2: Array<Number> = [1, 2, 3, 4, 5]

// 枚举类型
// 数字枚举
const enum Direction {
  NORTH,
  SOUTH,
  EAST,
  WEST
}
let dir: Direction = Direction.NORTH // 默认值为0,1,2,3,4，自动增长
// 字符串枚举
const enum Direction1 {
  NORTH = 'NORTH',
  SOUTH = 'SOUTH',
  EAST = 'EAST',
  WEST = 'WEST'
}
let dir1: Direction = Direction.NORTH // 'NORTH'
//常量枚举 添加const关键词即可
// 异构枚举 数字和字符串的组合

enum Direaction2 {
  DIRECTION,
  NORTH = 1,
  SOUTH = 'SOUTH',
  EAST = 'EAST',
  WEST = 2
}
// 这里会出现反向映射
console.log(Direaction2[0]) // 'DIRECTION'
console.log(Direaction2.DIRECTION) // 0

// any类型
let notSure: any = 66

// unknown
let value: unknown

// 元组类型
let pupleType: [String, Number] = ['1', 1]

// void 类型
function test(): void {
  console.log('this is a void type function')
}

// null undefined

let someValue: any = 'this is a string'
let strLength: number = (<string>someValue).length

let someValue1: any = 'this is a string'
let strLength1: number = (someValue1 as string).length

function myFunc(maybeString: string | undefined | null) {
  const onlyString: string = maybeString
}

let getStr: (str: string) => number = (str) => parseInt(str, 10)

// 定义对象数组
const arr: { age: string }[] = [{ age: 'dell' }]
// 规定某种对象格式
type User = {
  name: string
  age: number
}
const arr3: User[] = [{ name: '12', age: 12 }]
// 甚至可以定义一个类对象数组
class Teacher {
  name: string
  age: number
}
const arr4: Teacher[] = [new Teacher(), { name: '12', age: 12 }]
// 二位数组 + 元祖定义
const demo1: [string, number, string][] = [
  ['1', 2, '1'],
  ['2', 3, '3']
]

const getPersonName: (person: { name: string }) => string = (person) => person.name
const setPersonName: (person: { name: string }, name: string) => void = (person, name) => {
  person.name = name
}
// 改造成 Interface

interface Person {
  name: string
  age?: number
}
const getPersonName1: (person: Person) => string = (person) => person.name

// type 和 interface 的区别是 type可以去表示基础类型，接口只能表示对象

getPersonName1({ name: '1', age: 11 })

interface bird {
  fly: boolean
  sing: () => {}
}
interface dog {
  fly: boolean
  bark: () => {}
}

// 类型断言 你比 TS 更加知道类型，因为TS在联合类型下只会去取公有属性
// as
function trainAnial(animal: bird | dog): void {
  if (animal.fly) {
    ;(animal as bird).sing()
  } else {
    ;(animal as dog).bark()
  }
}
// in 判断属性名是否在该对象
function trainAnials(animal: bird | dog): void {
  if ('sing' in animal) {
    animal.sing()
  } else {
    animal.bark()
  }
}

// 类型保护 typeof instanceof
let addFirst: (num1: number | string, num2: number | string) => any = (num1, num2) => {
  if (typeof num1 === 'string' || typeof num2 === 'string') {
    return `${num1}${num2}`
  }
  return num1 + num2
}
